//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#ifndef __BUTTON_DRIVER_H__
#define __BUTTON_DRIVER_H__

#include "../../BSP/GPIO_BSP/gpio_bsp.h"
#include "../../BSP/EXTI_BSP/exti_bsp.h"//由于外部中断配合按键过于复杂，本次放弃使用外部中断
#include "../../BSP/ADC_BSP/adc_bsp.h"


#define Independent_Button_EN           1 //独立按键
#define Matrix_Button_EN                0 //矩阵按键
#define ADC_Button_Enable               0 //ADC按键

#define Independent_Button_EXTI_EN      (1 & Independent_Button_EN) //独立按键外部中断
#define Matrix_Button_EXTI_EN           (1 & Matrix_Button_EN)      //矩阵按键外部中断,矩阵外部中断先不使用且不实现

//独立按键个数
#define Independent_Button_Count        2
//矩阵按键个数
#define Matrix_Button_Row               4
#define Matrix_Button_Col               4
#define Matrix_Button_Count             (Matrix_Button_Row*Matrix_Button_Col)
//ADC按键个数
#define ADC_Button_Count                0



//独立按键
#define Independent_Button0_GPIO_Port	        PortA
#define Independent_Button0_GPIO_Pin	        Pin0

#define Independent_Button1_GPIO_Port           PortC
#define Independent_Button1_GPIO_Pin            Pin13

#define Independent_Button2_GPIO_Port           PortB
#define Independent_Button2_GPIO_Pin            Pin1

/*
矩阵按键如果使用引脚中断功能需要配置所有列的引脚中断，各引脚中断函数里面还要判断是那个列引起的中断，从而去扫描列对应的行。使用起来较为复杂，且pin脚相同的列GPIO配置中断会有冲突。
1、硬件上可使用一个多路输入的或门芯片（一般成本原因不会随意加的），通过芯片输出的信号引起引脚中断从而开启矩阵扫描。
2、不使用引脚中断。定时器每隔20毫秒去主动识别有按键按下不，如果有则主动开启扫描，直到没有一个按键按下。
3、一般情况下独立按键会默认使用引脚中断的。矩阵按键一般使用20毫秒监测按键或扫描按键。
说明：使用引脚中断的功能其实就是不循环扫描按键，一般大部分时间内，用户是不按下按键的，所以系统没有必要每隔20毫秒去扫描，引脚中断被触发后就表示有按键按下了，此时去启动扫描按键，直到没有一个按键按下，此时停止扫描。开启引脚中断。
*/
//独立按键引脚中断
#define Independent_Button0_EXTI_Line	        Exti_Line_Pin0
#define Independent_Button1_EXTI_Line           Exti_Line_Pin13
#define Independent_Button2_EXTI_Line           Exti_Line_Pin1


//矩阵按键
#define Matrix_Button_ROW0_GPIO_Port            PortB
#define Matrix_Button_ROW0_GPIO_Pin             Pin1

#define Matrix_Button_ROW1_GPIO_Port            PortB
#define Matrix_Button_ROW1_GPIO_Pin             Pin1

#define Matrix_Button_ROW2_GPIO_Port            PortB
#define Matrix_Button_ROW2_GPIO_Pin             Pin1

#define Matrix_Button_ROW3_GPIO_Port            PortB
#define Matrix_Button_ROW3_GPIO_Pin             Pin1

#define Matrix_Button_COL0_GPIO_Port            PortB
#define Matrix_Button_COL0_GPIO_Pin             Pin1

#define Matrix_Button_COL1_GPIO_Port            PortB
#define Matrix_Button_COL1_GPIO_Pin             Pin1

#define Matrix_Button_COL2_GPIO_Port            PortB
#define Matrix_Button_COL2_GPIO_Pin             Pin1

#define Matrix_Button_COL3_GPIO_Port            PortB
#define Matrix_Button_COL3_GPIO_Pin             Pin1


//列的引脚中断线不能一样，对于STM32F10x,列的Pin脚号不能一样(如果有一样的可以使用行的调换下，如还未解决建议放弃矩阵按键的引脚中断功能)
#define Matrix_Button_COL0_EXTI_Line            Exti_Line_Pin1
#define Matrix_Button_COL1_EXTI_Line            Exti_Line_Pin1
#define Matrix_Button_COL2_EXTI_Line            Exti_Line_Pin1
#define Matrix_Button_COL3_EXTI_Line            Exti_Line_Pin1


//ADC按键，由于本人的adc驱动未完成，故先不做adc按键了（预计思路是，开启adc通路x，采样率设计大概10毫秒，是adc按键扫描率的2倍。adc按键扫描的时候直接读取此路adc的值即可）
#define ADC_Button0                     Channel_1


typedef enum
{
	Independent_Button0 = 0,
	Independent_Button1,
	Independent_Button2,
	Independent_Button3,
	Independent_Button4,
	Independent_Button5,
	Independent_Button6,
	Independent_Button7,
	Independent_Button8,
	Independent_Button9,
	Independent_Button10,
	Independent_Button11,
	Independent_Button12,
	Independent_Button13,
	Independent_Button14,
	Independent_Button15,
	Independent_Button16,
	Independent_Button17,
	Independent_Button18,
	Independent_Button19,
	Independent_Button20,
	Independent_Button21,
	Independent_Button22,
	Independent_Button23,
	Independent_Button24,
	Independent_Button25,
	Independent_Button26,
	Independent_Button27,
	Independent_Button28,
	Independent_Button29,
	Independent_Button30,
	Independent_Button31,
	ALL_Independent_Button,
}WHT_Independent_Button_Number_enum;//独立按键锁定最大32个按键

typedef enum
{
	Matrix_Button_Col0 = 0,
	Matrix_Button_Col1 = 1,
	Matrix_Button_Col2 = 2,
	Matrix_Button_Col3 = 3,
	Matrix_Button_Col4 = 4,
	Matrix_Button_Col5 = 5,
	Matrix_Button_Col6 = 6,
	Matrix_Button_Col7 = 7,
	ALL_Matrix_Button_Col,
}WHT_Matrix_Button_Col_enum;//一般项目中顶多也就8*8的矩阵按键了吧

typedef enum
{
    Button_No_Down = 0,//按键未按下
	Button_Yes_Down= 1,//按下
	Button_Down_Up = 2,//按下并松手
}WHT_Button_State_enum;//按键的3种状态

typedef void (*WHT_Button_Interrupt_Callback_t)(void);//按键按下回调函数

typedef struct
{
    WHT_Button_State_enum state;//当前按键的状态
    uint16_t Down_Count;        //按下扫描次数
	uint16_t Down_Time;         //应用层使用，本文件不使用。Down_Time = Down_Count *扫描速率(如20毫秒)
}WHT_Button_State_t;//按键的属性

typedef struct
{
#if Independent_Button_EN
	WHT_Button_State_t Independent_Button_State[Independent_Button_Count];
#endif
#if Matrix_Button_EN
	WHT_Button_State_t Matrix_Button_State[Matrix_Button_Row][Matrix_Button_Col];
#endif
#if ADC_Button_EN
	WHT_Button_State_t ADC_Button_State[ADC_Button_Count];
#endif
}WHT_Button_All_State_t;//所有按键的状态结构体


typedef struct
{
	const volatile uint32_t* WHT_Independent_Button_Exti_Flag;											 //bit0=1表示独立按键0按下
	const volatile uint32_t* WHT_Matrix_Button_Col_Exti_Flag; 											 //bit0=1表示矩阵列0按下
	volatile WHT_Button_All_State_t* WHT_Button_State;                             						 //所有按键的状态
	void (*WHT_Independent_Button_Exti_Config)(const WHT_Button_Interrupt_Callback_t interrupt_callback);//独立按键外部中断回调函数的配置
	void (*WHT_Matrix_Button_Exti_Config)(const WHT_Button_Interrupt_Callback_t interrupt_callback);     //矩阵按键外部中断回调函数的配置
	void (*WHT_Independent_Button_Exti_Enable)(WHT_Independent_Button_Number_enum number);				 //独立按键开启中断
	void (*WHT_Matrix_Button_Exti_Enable)(WHT_Matrix_Button_Col_enum colx);               				 //矩阵按键开启中断
	WHT_Button_State_enum (*WHT_Get_Independent_Button_State)(void);             						 //获取所有独立按键是否有按下
	WHT_Button_State_enum (*WHT_Get_Matrix_Button_State)(void);                    						 //获取所有矩阵按键是否有按下
	void (*WHT_Independent_Button_Scan)(WHT_Independent_Button_Number_enum number);						 //独立按键扫描
	void (*WHT_Matrix_Button_Scan)(WHT_Matrix_Button_Col_enum colx);              						 //矩阵按键扫描
}WHT_Button_Driver_t;

extern void WHT_Button_Driver_Register(WHT_Button_Driver_t* driver);

#endif // !__BUTTON_DRIVER_H__
